#include "tim2.h"

uint32_t counter = 0; // tim2周期为 20ms = 0.02s 


void tim2_init(void)
{
    /*开启外设时钟*/
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); 
    /*设置tim2时钟来源为内部时钟*/
    TIM_InternalClockConfig(TIM2);

    /*配置时基单元*/
    TIM_TimeBaseInitTypeDef TIM2_InitStruct;
    TIM2_InitStruct.TIM_ClockDivision = TIM_CKD_DIV1;  //时钟源分频,这里选1分频
    TIM2_InitStruct.TIM_CounterMode	= TIM_CounterMode_Up;//计数器模式 这里选择向上计数 (此外还有向下计数, 中央对齐计数等)
    TIM2_InitStruct.TIM_RepetitionCounter = 0;//重复计数器的值 高级定时器才有, 这里用不上直接给零
    /*设置定时器周期 20ms*/
    TIM2_InitStruct.TIM_Prescaler = 72 - 1;	//PSC预分频器的值
    TIM2_InitStruct.TIM_Period = 20000 - 1; 	//周期 即ARR自动重装器的值
    TIM_TimeBaseInit(TIM2, &TIM2_InitStruct); //初始化配置函数

    /*清除复位时产生的一次更新中断*/
    TIM_ClearFlag(TIM2, TIM_FLAG_Update);

    /*中断配置*/
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE); //使能更新中断 TIM_ITConfig()

    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn; //指定中断通道开启/关闭  这里选择 TIM2号中断通道 对应 TIM2
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; //指定中断通道使能/失能		
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 3;	//指定所选通道的抢占优先级
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; //指定所选通道的响应优先级
    NVIC_Init(&NVIC_InitStruct); //初始化

    /*pwm输出*/
    /*pwm GPIO
    TIM2_CH1 --> PA0
    TIM2_CH2 --> PA1
    TIM2_CH3 --> PA2
    TIM2_CH4 --> PA3*/
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);			//开启GPIOA的时钟
    GPIO_InitTypeDef GPIO_InitStructure;
	  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	  GPIO_Init(GPIOA, &GPIO_InitStructure);							//将PA1引脚初始化为复用推挽输出	 受外设控制的引脚，均需要配置为复用模式

    /*输出比较初始化*/ 
    TIM_OCInitTypeDef TIM_OCInitStructure;							//定义结构体变量
	  TIM_OCStructInit(&TIM_OCInitStructure);                         //结构体初始化，若结构体没有完整赋值
	                                                                //则最好执行此函数，给结构体所有成员都赋一个默认值
	                                                                //避免结构体初值不确定的问题
	  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;               //输出比较模式，选择PWM模式1
	  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       //输出极性，选择为高，若选择极性为低，则输出高低电平取反
	  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   //输出使能
	  TIM_OCInitStructure.TIM_Pulse = 0;								//初始的CCR值

    TIM_OC1Init(TIM2, &TIM_OCInitStructure);                        //将结构体变量交给TIM_OC1Init，配置TIM2的输出比较通道1
    TIM_OC2Init(TIM2, &TIM_OCInitStructure);                        //将结构体变量交给TIM_OC2Init，配置TIM2的输出比较通道2

    /*启动计时器*/
    TIM_Cmd(TIM2, ENABLE); 
}

/**
  * 函    数：PWM设置CCR 输出比较通道1
  * 参    数：Compare 要写入的CCR的值
  * 返 回 值：无
  * 注意事项：CCR和ARR共同决定占空比，此函数仅设置CCR的值，并不直接是占空比
  *           占空比Duty = CCR / (ARR + 1)
  */
void PWM_SetCompare1(uint16_t Compare)
{
	TIM_SetCompare1(TIM2, Compare);		//设置CCR的值
}


/**
  * 函    数：PWM设置CCR 输出比较通道2
  * 参    数：Compare 要写入的CCR的值
  * 返 回 值：无
  * 注意事项：CCR和ARR共同决定占空比，此函数仅设置CCR的值，并不直接是占空比
  *           占空比Duty = CCR / (ARR + 1)
  */
void PWM_SetCompare2(uint16_t Compare)
{
	TIM_SetCompare2(TIM2, Compare);		//设置CCR的值
}


//TIM2 中断函数
void TIM2_IRQHandler(void)
{
	//检查中断标志位 这里检查TIM2计时器的更新中断位
	if ( TIM_GetITStatus(TIM2, TIM_IT_Update) == SET )
	{
		counter ++;
		//清理标志位
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
	}
	
}